home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dr. Windows 3
/
dr win3.zip
/
dr win3
/
UTILITY1
/
MSWSRC35.ZIP
/
PAREN.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-11
|
9KB
|
312 lines
/*
* paren.c logo parenthesizing module dko
*
* Copyright (C) 1991 The Regents of the University of California
* This Software may be copied and distributed for educational,
* research, and not for profit purposes provided that this
* copyright and statement are included in all such copies.
*
*/
#include "logo.h"
#include "globals.h"
#define assign(to, from) to = reref(to, from)
NODE *the_generation;
typedef NODE *(*nodeinout)(NODE *arg);
/* Set the line pointer for a tree.
*/
void make_line(NODE *tree, NODE *line) {
/* setobject(tree, line); BH */
setobject(tree, NIL);
tree->n_obj = line;
settype(tree, LINE);
}
void untreeify(NODE *node) {
settreepair__tree(node, NIL);
settype(node, CONS);
}
void untreeify_line(NODE *line) {
if (line != NIL && is_list(line)) {
untreeify_line(car(line));
untreeify_line(cdr(line));
untreeify(line);
}
}
void untreeify_proc(NODE *procname) {
NODE *body = bodylist__procnode(procnode__caseobj(procname));
NODE *body_ptr;
for (body_ptr = body; body_ptr != NIL; body_ptr = cdr(body_ptr)) {
untreeify_line(car(body_ptr));
}
untreeify(body);
}
/* Treeify a body by appending the trees of the lines.
*/
void make_tree_from_body(NODE *body) {
NODE *body_ptr, *end_ptr = NIL, *tree = NIL;
if (body == NIL ||
(is_tree(body) && generation__tree(body) == the_generation))
return;
for (body_ptr = body; body_ptr != NIL; body_ptr = cdr(body_ptr)) {
tree = car(body_ptr);
assign(this_line, tree);
make_tree(tree);
if (is_tree(tree)) {
tree = tree__tree(tree);
make_line(tree, car(body_ptr));
if (end_ptr == NIL)
settree__tree(body, tree);
else
setcdr(end_ptr, tree);
if (generation__tree(car(body_ptr)) == UNBOUND)
setgeneration__tree(body, UNBOUND);
untreeify(car(body_ptr));
while (cdr(tree) != NIL)
tree = cdr(tree);
end_ptr = tree;
} else { /* error while treeifying */
untreeify(body);
return;
}
}
settype(body, TREE);
}
BOOLEAN tree_dk_how;
/* Treeify a list of tokens (runparsed or not).
*/
void make_tree(NODE *list) {
NODE *tree = NIL;
NODE *paren_line(NODE *);
if (list == NIL ||
(is_tree(list) && generation__tree(list) == the_generation))
return;
if (!runparsed(list)) make_runparse(list);
tree_dk_how = FALSE;
tree = paren_line(parsed__runparse(list));
if (tree != NIL && tree != UNBOUND) {
settype(list, TREE);
settree__tree(list, tree);
if (tree_dk_how || stopping_flag==THROWING)
setgeneration__tree(list, UNBOUND);
}
}
/* Fully parenthesize a complete line, i.e. transform it from a flat list
* to a tree.
*/
NODE *paren_line(NODE *line) {
NODE *retval = NIL;
// NODE *save = line;
NODE *paren_expr(NODE **expr, BOOLEAN inparen);
NODE *paren_infix(NODE *left, NODE **rest, int old_pri, BOOLEAN inparen);
if (line == NIL) return line;
retval = paren_expr(&line, FALSE);
if (NOT_THROWING && retval != UNBOUND) {
retval = paren_infix(retval, &line, -1, FALSE);
retval = cons(retval, paren_line(line));
}
return retval;
}
/* Parenthesize an expression. Set expr to the node after the first full
* expression.
*/
NODE *paren_expr(NODE **expr, BOOLEAN inparen) {
NODE *first = NIL, *tree = NIL, *proc, *retval;
// NODE *save = *expr;
NODE **ifnode = (NODE **)NIL;
NODE *gather_args(NODE *, NODE **, BOOLEAN, NODE **);
NODE *paren_infix(NODE *, NODE **, int, BOOLEAN);
if (*expr == NIL) {
if (inparen) err_logo(PAREN_MISMATCH, NIL);
return *expr;
}
first = valref(car(*expr));
pop(*expr);
if (nodetype(first) == CASEOBJ && !numberp(first)) {
if (first == Left_Paren) {
deref(first);
tree = paren_expr(expr, TRUE);
tree = paren_infix(tree, expr, -1, TRUE);
if (*expr == NIL)
err_logo(PAREN_MISMATCH, NIL);
else if (car(*expr) != Right_Paren)
{
int parens;
err_logo(TOO_MUCH, NIL); /* throw the rest away */
for (parens = 0; *expr; pop(*expr))
if (car(*expr) == Left_Paren)
parens++;
else if (car(*expr) == Right_Paren)
if (parens-- == 0) break;
}
else
pop(*expr);
retval = tree;
} else if (first == Right_Paren) {
deref(first);
err_logo(UNEXPECTED_PAREN, NIL);
if (inparen) push(first, *expr);
retval = NIL;
} else if (first == Minus_Sign) {
deref(first);
push(Minus_Tight, *expr);
retval = paren_infix(make_intnode((FIXNUM) 0), expr, -1, inparen);
} else { /* it must be a procedure */
if (procnode__caseobj(first) == UNDEFINED && NOT_THROWING &&
first != Null_Word)
silent_load(first, NULL); /* try ./<first>.lg */
if (procnode__caseobj(first) == UNDEFINED && NOT_THROWING &&
first != Null_Word)
silent_load(first, logolib); /* try <logolib>/<first> */
proc = procnode__caseobj(first);
if (proc == UNDEFINED && NOT_THROWING) {
retval = cons(first, NIL);
tree_dk_how = TRUE;
} else {
/* Kludge follows to turn IF to IFELSE sometimes. */
if (first == If) {
ifnode = &first;
}
retval = gather_args(proc, expr, inparen, ifnode);
if (retval != UNBOUND) {
retval = cons(first, retval);
}
}
deref(first);
}
} else if (is_list(first)) { /* quoted list */
retval = make_quote(first);
deref(first);
} else {
unref(first);
return first;
}
return retval;
}
/* Gather the correct number of arguments to proc into a list. Set args to
* immediately after the last arg.
*/
NODE *gather_args(NODE *proc, NODE **args, BOOLEAN inparen, NODE **ifnode) {
int min, max;
NODE *gather_some_args(int, int, NODE **, BOOLEAN, NODE **);
if (nodetype(proc) == CONS) {
min = (inparen ? getint(minargs__procnode(proc))
: getint(dfltargs__procnode(proc)));
max = (inparen ? getint(maxargs__procnode(proc))
: getint(dfltargs__procnode(proc)));
} else { /* primitive */
min = (inparen ? getprimmin(proc) : getprimdflt(proc));
if (min < 0) { /* special form */
return ((nodeinout)*getprimfun(proc))(*args);
}
/* Kludge follows to allow EDIT and CO without input without paren */
if (getprimmin(proc) == OK_NO_ARG) min = 0;
max = (inparen ? getprimmax(proc) : getprimdflt(proc));
}
return gather_some_args(min, max, args, inparen, ifnode);
}
/* Make a list of the next n expressions, where n is between min and max.
* Set args to immediately after the last expression.
*/
NODE *gather_some_args(int min, int max, NODE **args, BOOLEAN inparen,
NODE **ifnode)
{
// int parens;
NODE *paren_infix(NODE *left, NODE **rest, int old_pri, BOOLEAN inparen);
if (*args == NIL || car(*args) == Right_Paren ||
(nodetype(car(*args)) == CASEOBJ &&
nodetype(procnode__caseobj(car(*args))) == INFIX)) {
if (min > 0) return cons(Not_Enough_Node, NIL);
// if (*args == NIL || car(*args) == Right_Paren) {
// if (min > 0) return cons(Not_Enough_Node, NIL);
} else if (max == 0) {
if (ifnode != (NODE **)NIL && is_list(car(*args))) {
/* if -> ifelse kludge */
NODE *retval;
err_logo(IF_WARNING, NIL);
assign(*ifnode, Ifelse);
retval = paren_expr(args, FALSE);
retval = paren_infix(retval, args, -1, inparen);
return cons(retval, gather_some_args(min, max, args,
inparen, (NODE **)NIL));
}
} else {
if (max < 0) max = 0; /* negative max means unlimited */
if (car(*args) != Right_Paren &&
(nodetype(car(*args)) != CASEOBJ ||
nodetype(procnode__caseobj(car(*args))) != INFIX)) {
NODE *retval = paren_expr(args, FALSE);
// if (max < 0) max = 0; /* negative max means unlimited */
// if (car(*args) != Right_Paren) {
// NODE *retval = paren_expr(args, FALSE);
retval = paren_infix(retval, args, -1, inparen);
return cons(retva